[IA64] fixed switch to idle domain bug
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Fri, 17 Feb 2006 22:02:40 +0000 (15:02 -0700)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Fri, 17 Feb 2006 22:02:40 +0000 (15:02 -0700)
Previously when switching to idle domain, cr.pta is set to dom0's VHPT,
then when switching from VTIdomain to idle domain, cr.pta is set to
dom0's VHPT, and in idle domain, VHPT will be not remapped by TR, so
there may be unexpected vhpt fault in idle domain, which may cause
domain crash. Above only happens in host smp platform not host up
platform. This patch is intended to fix this bug.

Signed-off-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Anthony Xu <anthony.xu@intel.com>
xen/arch/ia64/xen/xenmisc.c
xen/include/asm-ia64/linux-xen/asm/processor.h

index 923f254ad44134df8e059235b1a224695841728c..fddfffdc0e9b857d5839c45fe448d72d6f568bfb 100644 (file)
@@ -295,6 +295,7 @@ unsigned long context_switch_count = 0;
 void context_switch(struct vcpu *prev, struct vcpu *next)
 {
     uint64_t spsr;
+    uint64_t pta;
 
     local_irq_save(spsr);
     if(VMX_DOMAIN(prev)){
@@ -302,9 +303,9 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
     }
        context_switch_count++;
        switch_to(prev,next,prev);
-    if(VMX_DOMAIN(current)){
-        vtm_domain_in(current);
-    }
+//    if(VMX_DOMAIN(current)){
+//        vtm_domain_in(current);
+//    }
 
 // leave this debug for now: it acts as a heartbeat when more than
 // one domain is active
@@ -317,18 +318,26 @@ if (!i--) { printk("+",id); i = 1000000; }
 }
 
     if (VMX_DOMAIN(current)){
+        vtm_domain_in(current);
                vmx_load_all_rr(current);
     }else{
-       extern char ia64_ivt;
-       ia64_set_iva(&ia64_ivt);
-       ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
-               VHPT_ENABLED);
+       extern char ia64_ivt;
+       ia64_set_iva(&ia64_ivt);
        if (!is_idle_domain(current->domain)) {
+               ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
+                       VHPT_ENABLED);
                load_region_regs(current);
                vcpu_load_kernel_regs(current);
-                   if (vcpu_timer_expired(current)) vcpu_pend_timer(current);
-       }
-           if (vcpu_timer_expired(current)) vcpu_pend_timer(current);
+                   if (vcpu_timer_expired(current))
+                vcpu_pend_timer(current);
+       }else {
+        /* When switching to idle domain, only need to disable vhpt
+        * walker. Then all accesses happen within idle context will
+        * be handled by TR mapping and identity mapping.
+        */
+           pta = ia64_get_pta();
+           ia64_set_pta(pta & ~VHPT_ENABLED);
+        }
     }
 
     local_irq_restore(spsr);
index 4b7f22da944455f8cc77926442f218f095186acd..2d2642f6660e408b0d38cb3c3d3998c3f1432bec 100644 (file)
@@ -639,6 +639,19 @@ ia64_get_ivr (void)
        return r;
 }
 
+#ifdef XEN
+/* Get the page table address and control bits.  */
+static inline __u64
+ia64_get_pta (void)
+{
+   __u64 r;
+   ia64_srlz_d();
+   r = ia64_getreg(_IA64_REG_CR_PTA);
+   ia64_srlz_d();
+   return r;
+}
+#endif
+
 static inline void
 ia64_set_dbr (__u64 regnum, __u64 value)
 {